#ifndef ROS_BRIDGE_H
#define ROS_BRIDGE_H

#include <tbox/main/module.h>
#include <tbox/eventx/work_thread.h>

#include <rclcpp/rclcpp.hpp>
#include <std_msgs/msg/string.hpp>
#include <std_msgs/msg/bool.hpp>
#include <example_interfaces/srv/add_two_ints.hpp>

namespace your {

class RosBridge : public tbox::main::Module {
 public:
  class Parent {
   public:
    virtual void on_Ros_ready() = 0;
    virtual void on_Ros_gotBool(bool value) = 0;
    virtual void on_Ros_addTwoInts(int a, int b, std::promise<int> &result) = 0;
  };

  explicit RosBridge(tbox::main::Context &ctx, Parent &parent);
  virtual ~RosBridge();

  virtual void onFillDefaultConfig(tbox::Json &js_this) override;
  virtual bool onInit(const tbox::Json &js_this) override;
  virtual bool onStart() override;
  virtual void onStop() override;
  virtual void toJson(tbox::Json &js) const;

 public:
  void pubText(const std::string &text);

  using AddTwoIntCallback = std::function<void(bool, int)>;
  void addTwoInt(int a, int b, AddTwoIntCallback &&cb);

 protected:
  void onTimerTick();
  void onTopicSubBool(const std_msgs::msg::Bool::SharedPtr msg);
  void onServiceAddTwoInts(const std::shared_ptr<rmw_request_id_t> request_header,
                           const std::shared_ptr<example_interfaces::srv::AddTwoInts::Request> req,
                           const std::shared_ptr<example_interfaces::srv::AddTwoInts::Response> rsp);

 private:
  Parent &parent_;
  tbox::eventx::WorkThread worker_;

  //! ros
  std::shared_ptr<rclcpp::Node> node_;
  rclcpp::TimerBase::SharedPtr ready_timer_;
  rclcpp::Publisher<std_msgs::msg::String>::SharedPtr pub_string_;
  rclcpp::Subscription<std_msgs::msg::Bool>::SharedPtr sub_bool_;
  rclcpp::Client<example_interfaces::srv::AddTwoInts>::SharedPtr  add_two_ints_client_;
  rclcpp::Service<example_interfaces::srv::AddTwoInts>::SharedPtr add_two_ints_service_;
};

}

#endif //ROS_BRIDGE_H
